package com.starview.platform.data;

/**
 * The IRelation is primarily a marker for the {@link Iterable} interface.
 * 
 * Note: we DO NOT include any means of determining the size of relations. This is important, as
 * computing the size of some relations is liable to be very expensive.
 * 
 * @author fgm
 * 
 */
public interface IRelation extends Iterable<IValue>, IValue
{
  /**
   * Find out if the relation is empty.
   * 
   * @return true if the relation is known to be empty
   */
  boolean isEmpty();

  /**
   * Return a measure of the size of the relation
   * 
   * @return the number of elements in the relation
   * 
   */
  int size();

  /**
   * Construct a 'shallow' copy of the relation. I.e., just copy the spine of the relation such that
   * modifying elements of the copy does not affect the original.
   * 
   * @return the copied relation. Any insertions, or deletions, of entries in the copy does not
   *         affect the original (and vice-versa).
   * @throws EvaluationException
   */
  @Override
  IRelation shallowCopy() throws EvaluationException;

  /**
   * Apply a transform to the relation to get a new one
   * 
   * @param transform
   * @return the new indexed relation
   * @throws EvaluationException
   */
  IRelation mapOver(IFunction transform) throws EvaluationException;

  /**
   * Apply a left associative reducing fold to the relation
   * 
   * @param transform
   * @param init
   *          the initial value of passed into the fold function as a 'zero'
   * @return the final result value by evaluating the transform for each element
   * @throws EvaluationException
   */
  IValue leftFold(IFunction transform, IValue init) throws EvaluationException;

  /**
   * Apply a right associative reducing fold to the relation
   * 
   * @param transform
   * @param init
   *          the initial value of passed into the fold function as a 'zero'
   * @return the final result value by evaluating the transform for each element
   * @throws EvaluationException
   */
  IValue rightFold(IFunction transform, IValue init) throws EvaluationException;

  /**
   * Test for equality using a supplied equality function
   * 
   * @param other
   * @param test
   * @return true if the elements are equal, according to the equality function
   * @throws EvaluationException
   */
  boolean equals(IRelation other, IFunction test) throws EvaluationException;
}
